// Copyright (c) Lawrence Livermore National Security, LLC and other VisIt
// Project developers.  See the top-level LICENSE file for dates and other
// details.  No copyright assignment is required to contribute to VisIt.

// ****************************************************************************
//  File: MeshViewerEnginePluginInfo.C
// ****************************************************************************

#include <MeshPluginInfo.h>
#include <avtMeshPlot.h>
#include <MeshAttributes.h>

//
// Storage for static data elements.
//
MeshAttributes *MeshViewerEnginePluginInfo::clientAtts = NULL;
MeshAttributes *MeshViewerEnginePluginInfo::defaultAtts = NULL;

// ****************************************************************************
//  Method:  MeshViewerEnginePluginInfo::InitializeGlobalObjects
//
//  Purpose:
//    Initialize the plot atts.
//
//  Programmer: generated by xml2info
//  Creation:   omitted
//
// ****************************************************************************
void
MeshViewerEnginePluginInfo::InitializeGlobalObjects()
{
    if (MeshViewerEnginePluginInfo::clientAtts == NULL)
    {
        MeshViewerEnginePluginInfo::clientAtts  = new MeshAttributes;
        MeshViewerEnginePluginInfo::defaultAtts = new MeshAttributes;
    }
}

// ****************************************************************************
//  Method: MeshViewerEnginePluginInfo::GetClientAtts
//
//  Purpose:
//    Return a pointer to the viewer client attributes.
//
//  Returns:    A pointer to the viewer client attributes.
//
//  Programmer: generated by xml2info
//  Creation:   omitted
//
// ****************************************************************************

AttributeSubject *
MeshViewerEnginePluginInfo::GetClientAtts()
{
    return clientAtts;
}

// ****************************************************************************
//  Method: MeshViewerEnginePluginInfo::GetDefaultAtts
//
//  Purpose:
//    Return a pointer to the viewer default attributes.
//
//  Returns:    A pointer to the viewer default attributes.
//
//  Programmer: generated by xml2info
//  Creation:   omitted
//
// ****************************************************************************

AttributeSubject *
MeshViewerEnginePluginInfo::GetDefaultAtts()
{
    return defaultAtts;
}

// ****************************************************************************
//  Method: MeshViewerEnginePluginInfo::SetClientAtts
//
//  Purpose:
//    Set the viewer client attributes.
//
//  Arguments:
//    atts      A pointer to the new client attributes.
//
//  Programmer: generated by xml2info
//  Creation:   omitted
//
// ****************************************************************************

void
MeshViewerEnginePluginInfo::SetClientAtts(AttributeSubject *atts)
{
    *clientAtts = *(MeshAttributes *)atts;
    clientAtts->Notify();
}

// ****************************************************************************
//  Method: MeshViewerEnginePluginInfo::GetClientAtts
//
//  Purpose:
//    Get the viewer client attributes.
//
//  Arguments:
//    atts      A pointer to return the client default attributes in.
//
//  Programmer: generated by xml2info
//  Creation:   omitted
//
// ****************************************************************************

void
MeshViewerEnginePluginInfo::GetClientAtts(AttributeSubject *atts)
{
    *(MeshAttributes *)atts = *clientAtts;
}

// ****************************************************************************
//  Method: MeshViewerEnginePluginInfo::AllocAvtPlot
//
//  Purpose:
//    Return a pointer to a newly allocated avt plot.
//
//  Returns:    A pointer to the newly allocated avt plot.
//
//  Programmer: generated by xml2info
//  Creation:   omitted
//
// ****************************************************************************

avtPlot *
MeshViewerEnginePluginInfo::AllocAvtPlot()
{
    return new avtMeshPlot;
}

// ****************************************************************************
//  Method: MeshViewerEnginePluginInfo::InitializePlotAtts
//
//  Purpose:
//    Initialize the plot attributes to the default attributes.
//
//  Programmer: Mark C. Miller 
//  Creation:   November 3, 2020
// ****************************************************************************
#include <avtPlotMetaData.h>

void
MeshViewerEnginePluginInfo::InitializePlotAtts(AttributeSubject *atts,
    const avtPlotMetaData &plot)
{
    *(MeshAttributes*)atts = *defaultAtts;
    SetAutonomousColors(atts,
        plot.GetBackgroundColor(), plot.GetForegroundColor());
}

// ****************************************************************************
//  Method: MeshViewerEnginePluginInfo::GetMenuName
//
//  Purpose:
//    Return a pointer to the name to use in the viewer menus.
//
//  Returns:    A pointer to the name to use in the viewer menus.
//
//  Programmer: generated by xml2info
//  Creation:   omitted
//
// ****************************************************************************

const char *
MeshViewerEnginePluginInfo::GetMenuName() const
{
    return "Mesh";
}

// ****************************************************************************
//  Method: MeshViewerEnginePluginInfo::SetAutonomousColors
//
//  Purpose:
//    Sets the color for any autonomous color selection modes 
//
//  Programmer: Mark C. Miller 
//  Creation:   November 3, 2020
// ****************************************************************************
#include <avtColorTables.h>

void
MeshViewerEnginePluginInfo::SetAutonomousColors(AttributeSubject *atts,
    double const *bgColor, double const *fgColor)
{
    MeshAttributes *meshAtts = (MeshAttributes *)atts;
    bool attsChanged = false;

    unsigned char bg[3] = {static_cast<unsigned char>(bgColor[0]*255),
                           static_cast<unsigned char>(bgColor[1]*255),
                           static_cast<unsigned char>(bgColor[2]*255)};
    unsigned char fg[3] = {static_cast<unsigned char>(fgColor[0]*255),
                           static_cast<unsigned char>(fgColor[1]*255),
                           static_cast<unsigned char>(fgColor[2]*255)};

    if (meshAtts->GetOpaqueColorSource() == MeshAttributes::OpaqueRandom)
    {
        unsigned char rgb[3] = {bg[0], bg[1], bg[2]};

        // deconflict opaque color with foreground
        avtColorTables *ct = avtColorTables::Instance();
        if (!ct->GetJNDControlPointColor(ct->GetDefaultDiscreteColorTable(),
                                            "MeshColor", fg, rgb))
            ct->GetJNDControlPointColor("distinct", "MeshColor", fg, rgb);

        ColorAttribute c(rgb[0], rgb[1], rgb[2]);
        meshAtts->SetOpaqueColor(c);
        attsChanged = true;
    }

    if (meshAtts->GetMeshColorSource() == MeshAttributes::MeshRandom)
    {
        unsigned char rgb[3] = {fg[0], fg[1], fg[2]};
        ColorAttribute opqc = meshAtts->GetOpaqueColor();

        // deconflict mesh (lines) color with opaque color
        avtColorTables *ct = avtColorTables::Instance();
        if (!ct->GetJNDControlPointColor(ct->GetDefaultDiscreteColorTable(),
                                            "MeshColor", opqc.GetColor(), rgb))
            ct->GetJNDControlPointColor("distinct", "MeshColor", opqc.GetColor(), rgb);

        ColorAttribute c(rgb[0], rgb[1], rgb[2]);
        meshAtts->SetMeshColor(c);
        attsChanged = true;
    }

    // Ensure GUI reflects any color choices made here
    if (attsChanged)
        SetClientAtts(atts);
}

